/*
* Copyright 2010 Pavel Kozhin 
*
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed  under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License.
*
* Author: Pavel Kozhin.
*/

package org.etherframework.behaviour.rules.core
{
	import org.etherframework.behaviour.rules.context.Context;
	import org.etherframework.behaviour.rules.context.ContextEvent;
	import org.etherframework.behaviour.rules.context.IContext;
	import org.etherframework.behaviour.rules.controls.helpers.Fault;
	import org.etherframework.behaviour.rules.events.FeedbackEvent;
	import org.etherframework.behaviour.rules.util.ContextResolver;
	import org.etherframework.behaviour.rules.util.FeedbackHelper;
	import org.etherframework.core.ether_internal;
	
	import flash.events.EventDispatcher;
	
	import mx.core.EventPriority;
	import mx.core.mx_internal;
	
	use namespace mx_internal;
	
	use namespace ether_internal;
	
	[Exclude(name="activate", kind="event")]
	
	[Exclude(name="deactivate", kind="event")]
	
	[Exclude(name="descriptor", kind="property")]
	
	[Event(name="contextIn", type="org.etherframework.behaviour.rules.events.FeedbackEvent")]
	
	[Event(name="contextOpen", type="org.etherframework.behaviour.rules.events.FeedbackEvent")]
	
	[Event(name="contextClose", type="org.etherframework.behaviour.rules.events.FeedbackEvent")]
	
	public class Control extends EventDispatcher implements IControl
	{
		private static const CONTEXT_IN_EVENT:String = "contextIn";
		
		private static const CONTEXT_OPEN_EVENT:String = "contextOpen";
		
		private static const CONTEXT_CLOSE_EVENT:String = "contextClose";
		
		private var eventPriority:int;
		
		public function Control()
		{
			eventPriority = EventPriority.CURSOR_MANAGEMENT;
			super();
		}
		
		public function initialize():void
		{
		}
		
		private var _id:String;

		public function get id():String
		{
			return _id;
		}

		public function set id(value:String):void
		{
			_id = value;
		}
		
		private var _feedbackId:String;

		public function get feedbackId():String
		{
			return _feedbackId;
		}

		public function set feedbackId(value:String):void
		{
			_feedbackId = value;
		}
		
		private var _index:int = -1;

		public function get index():int
		{
			return _index;
		}

		public function set index(value:int):void
		{
			_index = value;
		}
		
		private var _descriptor:Descriptor;
		
		public function get descriptor():Descriptor
		{
			return _descriptor;
		}
		
		public function set descriptor(value:Descriptor):void
		{
			_descriptor = value;
		}
		
		private var _context:IContext;
		
		[Bindable]
		public function get context():IContext
		{
			return _context;
		}
		
		public function set context(value:IContext):void
		{
			if (!value)
				return;
			
			value.removeEventListener(ContextEvent.CLOSE, contextCloseHandler);
			value.removeEventListener(ContextEvent.OPEN, contextOpenHandler);
			value.addEventListener(ContextEvent.CLOSE, contextCloseHandler, false, eventPriority);
			value.addEventListener(ContextEvent.OPEN, contextOpenHandler, false, eventPriority);
			
			_context = value;
			
			dispatchFeedback(CONTEXT_IN_EVENT);
		}
		
		public function dispatchFeedback(type:String):void
		{
			var evt:FeedbackEvent = new FeedbackEvent(type);
			evt.context = _context;
			evt.output = context.output ? context.output.value : null;
			evt.lastOutput = context.lastOutput ? context.lastOutput.value : null;
			
			ContextResolver.resolve(this);
			
			if (dispatchEvent(evt))
			{
				FeedbackHelper.feedback(this, evt.clone() as FeedbackEvent, type);
			}
		}
		
		private function contextOpenHandler(event:ContextEvent):void
		{
			event.target.removeEventListener(event.type, contextOpenHandler);
			
			dispatchFeedback(CONTEXT_OPEN_EVENT);
		}
		
		private function contextCloseHandler(event:ContextEvent):void
		{
			event.target.removeEventListener(event.type, contextCloseHandler);
			
			dispatchFeedback(CONTEXT_CLOSE_EVENT);
		}
		
	}
}